package com.pucong.gitee.database.backup.business.sys.service;


import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.pucong.gitee.database.backup.business.sys.mapper.SysConfigMapper;
import com.pucong.gitee.database.backup.business.sys.mapper.SysFileMapper;
import com.pucong.gitee.database.backup.common.entity.sys.ChangeFileStatusVo;
import com.pucong.gitee.database.backup.common.entity.sys.SysFile;
import com.pucong.gitee.database.backup.common.entity.sys.UserJwt;
import com.pucong.gitee.database.backup.common.selfenum.FileStatusEnum;
import com.pucong.gitee.database.backup.configuration.exception.BusinessException;
import com.pucong.gitee.database.backup.utils.ApplicationContextUtil;
import com.pucong.gitee.database.backup.utils.FileUtil;
import com.pucong.gitee.database.backup.utils.UUID;
import com.pucong.gitee.database.backup.utils.UserRequest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;


/**
 * 附件操作 service实现类
 *
 * @author pucong
 * @company gitee.com/pucong
 * @create 2020-12-02
 */
@Service
@Slf4j
public class SysFileServiceImpl implements SysFileService {

    @Autowired
    private SysFileMapper sysFileMapper;

    @Autowired
    private SysConfigMapper sysConfigMapper;

    @Override
    public SysFile getSysFileById(String id){
        return sysFileMapper.selectById(id);
    }

    @Override
    public List<SysFile> getSysFileByBusinessId(String businessId) {
        LambdaQueryWrapper<SysFile> sysFileParams = new LambdaQueryWrapper<>();
        sysFileParams.eq(SysFile::getBusinessId,businessId);
        List<SysFile> sysFiles = sysFileMapper.selectList(sysFileParams);
        return sysFiles;
    }

    @Override
    public SysFile uploadFile(MultipartFile file) {
        UserJwt loginUser = UserRequest.getLoginUser();
        // 获取文件名
        String fileNameOld = file.getOriginalFilename();
        if(fileNameOld.lastIndexOf(".") <= 0){
            throw new BusinessException("上传文件后缀错误，请设置后缀再上传:" + fileNameOld);
        }
        // 去掉文件夹名称
        int i = fileNameOld.indexOf("/") + 1;
        if(i > 0){
            fileNameOld = fileNameOld.substring(i);
        }
        // 获取文件的后缀名
        String suffixName = fileNameOld.substring(fileNameOld.lastIndexOf("."));
        // 解决中文问题，liunx下中文路径，图片显示问题
        String fileName = UUID.getSerializNo() + UUID.uuid() + suffixName;

        // 设置上传路径
        String path = getTmpPath() + File.separator + fileName;
        // 上传
        FileUtil.uploadFile(file,path);
        // 插入附件信息
        SysFile sysFile = new SysFile();
        sysFile.setUuid(UUID.uuid());
        sysFile.setFileName(fileName);
        sysFile.setFileNameOld(fileNameOld);
        sysFile.setFileSize(file.getSize() + "");
        sysFile.setFileType(suffixName);
        sysFile.setPath(path);
        sysFile.setCreateBy(loginUser.getUuid());
        sysFile.setCreateDate(new Date());
        sysFile.setFileStatus(FileStatusEnum.临时文件);
        sysFileMapper.insert(sysFile);
        return sysFile;
    }

    @Override
    public int deleteFileById(String id) {
        SysFile sysFile = sysFileMapper.selectById(id);
        deleteFile(id,sysFile.getPath());
        return 1;
    }

    @Transactional(propagation = Propagation.REQUIRED,rollbackFor = Exception.class)
    private void deleteFile(String id,String path){
        int i = sysFileMapper.deleteById(id);
        // 删除文件
        FileUtil.deleteFile(path);
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED,rollbackFor = Exception.class)
    public int deleteFileByBusinessId(String businessId) {
        LambdaQueryWrapper<SysFile> selectParams = new LambdaQueryWrapper<>();
        selectParams.eq(SysFile::getBusinessId, businessId);
        selectParams.eq(SysFile::getFileStatus, FileStatusEnum.正式文件);
        List<SysFile> sysFiles = sysFileMapper.selectList(selectParams);
        for (SysFile sysFile : sysFiles) {
            deleteFile(sysFile.getUuid(),sysFile.getPath());
        }
        return sysFiles.size();
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED,rollbackFor = Exception.class)
    public int updateDocChangeStatus(ChangeFileStatusVo changeFileStatusVo) {
        if (changeFileStatusVo.getFileIdList() == null || changeFileStatusVo.getFileIdList().size() == 0) {
            throw new BusinessException("传入参数错误");
        }
        if (StringUtils.isBlank(changeFileStatusVo.getBusinessId())) {
            throw new BusinessException("传入参数错误");
        }
        // 获取文件信息，对比找出需要删除的文件
        LambdaQueryWrapper<SysFile> selectParams = new LambdaQueryWrapper<>();
        selectParams.eq(SysFile::getBusinessId,changeFileStatusVo.getBusinessId());
        List<SysFile> sysFiles = sysFileMapper.selectList(selectParams);
        List<String> collect = sysFiles.stream().map(SysFile::getUuid).collect(Collectors.toList());
        collect.removeAll(changeFileStatusVo.getFileIdList());
        for (String fileId : collect) {
            deleteFileById(fileId);
        }
        SysFile update = new SysFile();
        update.setBusinessId(changeFileStatusVo.getBusinessId());
        update.setFileStatus(FileStatusEnum.正式文件);
        LambdaQueryWrapper<SysFile> updateParams = new LambdaQueryWrapper<>();
        updateParams.in(SysFile::getUuid,changeFileStatusVo.getFileIdList());
        int i = sysFileMapper.update(update,updateParams);
        return i;
    }

    @Override
    public void downLoadFileById(String uuid, HttpServletRequest request, HttpServletResponse response) {
        SysFile sysFile = sysFileMapper.selectById(uuid);
        if(sysFile == null){
            throw new BusinessException("传入参数错误");
        }
        FileUtil.downLoadFile(sysFile.getPath(),sysFile.getFileNameOld(),response);
    }

    @Override
    public void lookFileById(String uuid, HttpServletRequest request, HttpServletResponse response) {
        SysFile sysFile = sysFileMapper.selectById(uuid);
        if(sysFile == null){
            throw new BusinessException("传入参数错误");
        }
        FileUtil.lookFile(sysFile.getPath(),sysFile.getFileNameOld(),response);
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED,rollbackFor = Exception.class)
    public void deleteTmpFile() {
        LambdaQueryWrapper<SysFile> selectParams = new LambdaQueryWrapper<>();
        selectParams.eq(SysFile::getFileStatus, FileStatusEnum.临时文件);
        List<SysFile> sysFiles = sysFileMapper.selectList(selectParams);
        for (SysFile sysFile : sysFiles) {
            deleteFile(sysFile.getUuid(),sysFile.getPath());
        }
        // 删除缓存文件
        String path = ApplicationContextUtil.getSystemBasePath() + File.separator + "tmp";
        log.info("删除缓存文件：" + path);
        File file = new File(path);
        FileUtil.delFile(file);
    }

    public String getUploadPath() {
        return ApplicationContextUtil.getSystemBasePath() + File.separator + "dataFiles" ;
    }

    public String getTmpPath() {
        return ApplicationContextUtil.getSystemBasePath() + File.separator + "tmp" ;
    }
}
